//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package admin_auth_api_serv

import (
	"context"

	"gitcode.com/eteam/api-server/dao"
	"gitcode.com/eteam/proto-gen-go.git/admin_auth_api"
	"github.com/dchest/uniuri"
	"golang.org/x/crypto/ssh"
)

type AdminAuthApiImpl struct {
	admin_auth_api.UnimplementedAdminAuthApiServer
	pubKey string
}

func NewAdminAuthApiImpl(pubKey string) *AdminAuthApiImpl {
	return &AdminAuthApiImpl{pubKey: pubKey}
}

func (apiImpl *AdminAuthApiImpl) PreAuth(ctx context.Context, req *admin_auth_api.PreAuthRequest) (*admin_auth_api.PreAuthResponse, error) {
	chars := []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
	adminSessionId := ""
	for {
		tmpId := uniuri.NewLenChars(64, chars)
		_, ok := dao.CacheDao.GetAdminSession(ctx, tmpId)
		if !ok {
			adminSessionId = tmpId
			break
		}
	}
	toSignStr := uniuri.NewLenChars(256, chars)

	err := dao.CacheDao.SetAdminSession(ctx, &dao.AdminSessionDbItem{
		AdminSessionId: adminSessionId,
		UserName:       req.UserName,
		ToSignStr:      toSignStr,
		AuthOk:         false,
	})
	if err != nil {
		return nil, err
	}

	return &admin_auth_api.PreAuthResponse{
		Code:           admin_auth_api.PreAuthResponse_CODE_OK,
		AdminSessionId: adminSessionId,
		ToSignStr:      toSignStr,
	}, nil
}

func (apiImpl *AdminAuthApiImpl) Auth(ctx context.Context, req *admin_auth_api.AuthRequest) (*admin_auth_api.AuthResponse, error) {
	//检查会话
	sess, ok := dao.CacheDao.GetAdminSession(ctx, req.AdminSessionId)
	if !ok {
		return &admin_auth_api.AuthResponse{
			Code:   admin_auth_api.AuthResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	if sess.AuthOk {
		return &admin_auth_api.AuthResponse{
			Code: admin_auth_api.AuthResponse_CODE_OK,
		}, nil
	}

	pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(apiImpl.pubKey))
	if err != nil {
		return nil, err
	}
	err = pubKey.Verify([]byte(sess.ToSignStr), &ssh.Signature{
		Format: req.Sign.Format,
		Blob:   req.Sign.Blob,
		Rest:   req.Sign.Rest,
	})
	if err != nil {
		return &admin_auth_api.AuthResponse{
			Code:   admin_auth_api.AuthResponse_CODE_WRONG_SIGN,
			ErrMsg: "错误的签名",
		}, nil
	}
	sess.ToSignStr = ""
	sess.AuthOk = true
	err = dao.CacheDao.SetAdminSession(ctx, sess)
	if err != nil {
		return nil, err
	}
	return &admin_auth_api.AuthResponse{
		Code: admin_auth_api.AuthResponse_CODE_OK,
	}, nil
}

func (apiImpl *AdminAuthApiImpl) KeepAlive(ctx context.Context, req *admin_auth_api.KeepAliveRequest) (*admin_auth_api.KeepAliveResponse, error) {
	sess, ok := dao.CacheDao.GetAdminSession(ctx, req.AdminSessionId)
	if !ok {
		return &admin_auth_api.KeepAliveResponse{
			Code:   admin_auth_api.KeepAliveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if !sess.AuthOk {
		return &admin_auth_api.KeepAliveResponse{
			Code:   admin_auth_api.KeepAliveResponse_CODE_NOT_AUTH,
			ErrMsg: "未授权会话",
		}, nil
	}
	dao.CacheDao.KeepAdminSessionAlive(ctx, req.AdminSessionId) //skip error check

	return &admin_auth_api.KeepAliveResponse{
		Code: admin_auth_api.KeepAliveResponse_CODE_OK,
	}, nil
}
